home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / fs / fsSocketStubs.c < prev    next >
C/C++ Source or Header  |  1991-08-09  |  41KB  |  1,515 lines

  1. /* 
  2.  * socket.c --
  3.  *
  4.  *    Unix-compatibility routines to emulate 4.3 BSD socket-related
  5.  *    system calls for IPC using the Internet protocol suite. The
  6.  *    routines make calls to the Sprite Internet Server using Sprite
  7.  *    system calls.
  8.  *
  9.  *    Note: there is some redundance with ioctl routines (IOControl, etc.)
  10.  *    Some of these routines can be merged into the others.
  11.  *
  12.  * Copyright 1991 Regents of the University of California
  13.  * All rights reserved.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /sprite/src/kernel/fs/RCS/fsSocketStubs.c,v 1.2 91/08/09 14:54:19 shirriff Exp $ SPRITE (Berkeley)";
  18. #endif
  19.  
  20. #define MACH_UNIX_COMPAT
  21.  
  22. #include <sprite.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <user/bit.h>
  26. #include <user/dev/net.h>
  27. #include <user/fs.h>
  28. #include <user/inet.h>
  29. #include <user/status.h>
  30. #include <user/stdlib.h>
  31. #include <user/sys.h>
  32. #include <user/sys/types.h>
  33. #include <user/sys/file.h>
  34. #include <user/sys/uio.h>
  35. #include <user/errno.h>
  36. #include <mach.h>
  37. #include <fsUnixStubs.h>
  38. #include <vm.h>
  39. #include <proc.h>
  40. #include <fs.h>
  41. #include <fsio.h>
  42. #include <fsutil.h>
  43. #include <compatInt.h>
  44.  
  45. extern Mach_State    *machCurStatePtr;
  46.  
  47. static ReturnStatus IOControlStub _ARGS_ ((int streamID, int command,
  48.     int inBufSize, Address inBuffer, int outBufSize, Address outBuffer));
  49.  
  50. static char *errs[] = {"ENOERR", "EPERM", "ENOENT", "ESRCH", "EINTR", "EIO",
  51.         "ENXIO", "E2BIG", "ENOEXEC", "EBADF", "ECHILD", "EAGAIN", "ENOMEM",
  52.         "EACCES", "EFAULT", "ENOTBLK", "EBUSY", "EEXIST", "EXDEV", "ENODEV",
  53.         "ENOTDIR", "EISDIR", "EINVAL", "ENFILE", "EMFILE", "ENOTTY",
  54.         "ETXTBSY", "EFBIG", "ENOSPC", "ESPIPE", "EROFS", "EMLINK", "EPIPE",
  55.         "EDOM", "ERANGE", "EWOULDBLOCK", "EINPROGRESS", "EALREADY", "ENOTSOCK",
  56.         "EDESTADDRREQ", "EMSGSIZE", "EPROTOTYPE", "ENOPROTOOPT",
  57.         "EPROTONOSUPPORT", "ESOCKTNOSUPPORT", "EOPNOTSUPP", "EPFNOSUPPORT",
  58.         "EAFNOSUPPORT", "EADDRINUSE", "EADDRNOTAVAIL", "ENETDOWN",
  59.         "ENETUNREACH", "ENETRESET", "ECONNABORTED", "ECONNRESET", "ENOBUFS",
  60.         "EISCONN", "ENOTCONN", "ESHUTDOWN", "ETIMEDOUT", "ECONNREFUSED",
  61.         "ELOOP", "ENAMETOOLONG", "EHOSTDOWN", "EHOSTUNREACH", "ENOTEMPTY",
  62.         "EPROCLIM", "EUSERS", "EDQUOT", "ESTALE", "EREMOTE"};
  63.  
  64. #undef Mach_SetErrno
  65. #define Mach_SetErrno(err) if (debugFsStubs) \
  66.         printf("Error %d (%s) at %d in %s\n", err,\
  67.         err<sizeof(errs)/sizeof(char *)?errs[err]:"",\
  68.         __LINE__, __FILE__); Proc_GetActualProc()->unixErrno = (err)
  69.  
  70. #if 1
  71. #define    DebugMsg(status, string) printf("%x: %s\n", status, string)
  72. #else
  73. #define    DebugMsg(status, string)    ;
  74. #endif
  75.  
  76. static char streamDevice[276]; /* Max host name + extra format */
  77. static char dgramDevice[276];
  78. static char rawDevice[276];
  79. static Boolean gotHostName = FALSE;
  80.  
  81. extern char sysHostName[];
  82.  
  83. extern int debugFsStubs;
  84.  
  85.  
  86. /*
  87.  *----------------------------------------------------------------------
  88.  *
  89.  * accept --
  90.  *
  91.  *    Accept a stream connection request. This call will create a new
  92.  *    connection to the Inet server upon notification that a remote
  93.  *    connection request is pending.
  94.  *
  95.  *    If the socket is non-blocking and no remote connection requests are
  96.  *    pending, EWOULDBLOCK is returned. If the socket is blockable,
  97.  *    this routine will wait until a remote connection request arrives.
  98.  *
  99.  * Results:
  100.  *    If > 0, the stream ID of the new connection.
  101.  *    If UNIX_ERROR, errno = 
  102.  *    EINVAL        - Bad size for *namePtr.
  103.  *    EWOULDBLOCK    - Non pending requests.
  104.  *
  105.  * Side effects:
  106.  *    A new stream is created.
  107.  *
  108.  *----------------------------------------------------------------------
  109.  */
  110. #define UNIXRETURN(status) if (status==SUCCESS) { return 0; } else {\
  111.         Mach_SetErrno(Compat_MapCode(status)); return -1; }
  112.  
  113. int
  114. Fs_AcceptStub(socketID, addrPtr, addrLenPtr)
  115.     int            socketID;    /* Socket to listen on. */
  116.     struct sockaddr_in    *addrPtr;    /* Address of newly-accepted 
  117.                      * connection. (out) */
  118.     int            *addrLenPtr;    /* Size of *addrPtr. (in/out) */
  119. {
  120.     ReturnStatus    status;
  121.     int            newSocket;
  122.     int            addrLen;
  123.  
  124.     Address        usp;
  125.     int            *newSocketPtr;
  126.     ClientData        *acceptTokenPtr;
  127.     struct sockaddr_in    addr;
  128.  
  129.     usp = (Address)Mach_UserStack();
  130.     newSocketPtr = (int *)(usp - sizeof(int));
  131.     acceptTokenPtr = (ClientData *) (usp - sizeof(int) - sizeof(ClientData));
  132.  
  133.     if (addrLenPtr == (int *) NULL) {
  134.     addrLen = 0;
  135.     addrPtr = (struct sockaddr_in *) NULL;
  136.     } else {
  137.     /*
  138.      * We deal with just Internet sockets.
  139.      */
  140.     status = Vm_CopyIn(sizeof(addrLen), (Address)addrLenPtr, 
  141.                (Address)&addrLen);
  142.     if (status != SUCCESS) {
  143.         UNIXRETURN(status);
  144.     }
  145.     if (addrLen != sizeof(struct sockaddr_in)) {
  146.         UNIXRETURN(SYS_INVALID_ARG);
  147.     }
  148.     }
  149.  
  150.  
  151.     /*
  152.      * Tell the Inet server to accept connections on the socket.  If a
  153.      * connection is made, a token is returned that is used to convert the
  154.      * connection into a new socket.  If no connections are currently
  155.      * available and the socket is non-blocking, FS_WOULD_BLOCK is
  156.      * returned. If the socket is blockable, the ioctl returns
  157.      * NET_NO_CONNECTS so and Wait() must be used to wait for a
  158.      * connection.
  159.      */
  160.  
  161.     status = Fs_IOControlStub(socketID, IOC_NET_ACCEPT_CONN_1, 
  162.                 0, (Address) NULL, 
  163.             sizeof(ClientData), (Address) acceptTokenPtr);
  164.  
  165.     switch (status) {
  166.     case SUCCESS:
  167.         break;
  168.  
  169.     case FS_WOULD_BLOCK:
  170.         UNIXRETURN(FS_WOULD_BLOCK);
  171.  
  172.         case NET_NO_CONNECTS:
  173.         /*
  174.          * Wait for the server to tell us that a request has arrived.
  175.          */
  176.         (void) Wait(socketID, TRUE, (Time *) NULL);
  177.  
  178.         /*
  179.          * There's a pending connection so retry the ioctl.
  180.          */
  181.         status = Fs_IOControlStub(socketID, IOC_NET_ACCEPT_CONN_1, 
  182.                 0, (Address) NULL, 
  183.             sizeof(ClientData), (Address) acceptTokenPtr);
  184.         if (status != SUCCESS) {
  185.         DebugMsg(status, "accept (ioctl 1b)");
  186.         UNIXRETURN(status);
  187.         }
  188.         break;
  189.  
  190.     default:
  191.         DebugMsg(status, "accept (ioctl 1a)");
  192.         UNIXRETURN(status);
  193.     } 
  194.  
  195.  
  196.     /*
  197.      * Create the new socket. This socket will be converted into the new
  198.      * connection.
  199.      */
  200.  
  201.     status = Fs_OpenStub(streamDevice, FS_READ|FS_WRITE, 0666, newSocketPtr);
  202.     if (status != SUCCESS) {
  203.     DebugMsg(status, "accept (open)");
  204.     UNIXRETURN(status);
  205.     }
  206.     (void)Vm_CopyIn(sizeof(newSocket), (Address)newSocketPtr, 
  207.             (Address)&newSocket);
  208.  
  209.     /*
  210.      * Make the new socket have the same characteristics as the
  211.      * connection socket. Also, find out who we are connected to.
  212.      */
  213.     status = Fs_IOControlStub(newSocket, IOC_NET_ACCEPT_CONN_2, 
  214.             sizeof(ClientData), (Address) acceptTokenPtr, 
  215.             addrLen, (Address) addrPtr);
  216.  
  217.     if (status != SUCCESS) {
  218.     DebugMsg(status, "accept (ioctl 2)");
  219.     UNIXRETURN(status);
  220.     }
  221.     if (addrLen > 0) {
  222.     (void)Vm_CopyIn(addrLen, (Address)addrPtr, (Address)&addr);
  223.     addr.sin_family = AF_INET;
  224.     (void)Vm_CopyOut(addrLen, (Address)&addr, (Address)addrPtr);
  225.     }
  226.     return newSocket;
  227. }
  228. /*
  229.  *----------------------------------------------------------------------
  230.  *
  231.  * Fs_BindStub --
  232.  *
  233.  *    Assigns a local <address,port> tuple to a socket that does 
  234.  *    not have one.
  235.  *
  236.  * Results:
  237.  *    If 0        - Successful.
  238.  *    If UNIX_ERROR, then errno = 
  239.  *    EINVAL        - Bad size for *namePtr, already bound to an address.
  240.  *    EADDRINUSE    - The address is already in use.
  241.  *    EADDRNOTAVAIL    - The address is not valid for this host.
  242.  *
  243.  * Side effects:
  244.  *    The socket local address is set.
  245.  *
  246.  *----------------------------------------------------------------------
  247.  */
  248.  
  249. int 
  250. Fs_BindStub(socketID, namePtr, nameLen)
  251.     int            socketID;    /* Stream ID of unnamed socket. */
  252.     struct sockaddr    *namePtr;    /* Local address,port for this socket.*/
  253.     int            nameLen;    /* Size of *namePtr. */
  254. {
  255.     ReturnStatus    status;
  256.     Proc_ControlBlock *procPtr;
  257.     Fs_Stream      *streamPtr;
  258.     Fs_IOCParam ioctl;
  259.     Fs_IOReply reply;
  260.  
  261.     if (debugFsStubs) {
  262.     printf("Fs_BindStub(%d, %x, %d)\n", socketID, namePtr, nameLen);
  263.     }
  264.     if (nameLen != sizeof(struct sockaddr_in)) {
  265.     Mach_SetErrno(EINVAL);
  266.     return -1;
  267.     }
  268.  
  269.     procPtr = Proc_GetEffectiveProc();
  270.     status = Fs_GetStreamPtr(procPtr, socketID, &streamPtr);
  271.     if (status != SUCCESS) {
  272.     Mach_SetErrno(Compat_MapCode(status));
  273.     return -1;
  274.     }
  275.     if (!Fsutil_HandleValid(streamPtr->ioHandlePtr)) {
  276.     /* FS_STALE_HANDLE */
  277.     Mach_SetErrno(EINVAL);
  278.     return -1;
  279.     }
  280.     ioctl.command = IOC_NET_SET_LOCAL_ADDR;
  281.     ioctl.format = mach_Format;
  282.     ioctl.procID = procPtr->processID;
  283.     ioctl.familyID = procPtr->familyID;
  284.     ioctl.uid = procPtr->effectiveUserID;
  285.     ioctl.outBufSize = 0;
  286.     ioctl.outBuffer = NULL;
  287.     if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM) {
  288.     ioctl.inBufSize = nameLen;
  289.     ioctl.inBuffer = (Address)namePtr;
  290.     ioctl.flags = FS_USER_IN|FS_USER_OUT;
  291.     status = Fs_IOControl(streamPtr, &ioctl, &reply);
  292.     if (status != SUCCESS) {
  293.         Mach_SetErrno(Compat_MapCode(status));
  294.         return -1;
  295.     }
  296.     return 0;
  297.     }
  298.     ioctl.inBuffer = malloc(nameLen);
  299.     status = Vm_CopyIn(nameLen, (Address)namePtr, ioctl.inBuffer);
  300.     if (status != SUCCESS) {
  301.     free(ioctl.inBuffer);
  302.     Mach_SetErrno(EFAULT);
  303.     return -1;
  304.     }
  305.     status = Fs_IOControl(streamPtr, &ioctl, &reply);
  306.     free(ioctl.inBuffer);
  307.     if (status != SUCCESS) {
  308.     Mach_SetErrno(Compat_MapCode(status));
  309.     return -1;
  310.     }
  311.     return 0;
  312. }
  313.  
  314.  
  315. /*
  316.  *----------------------------------------------------------------------
  317.  *
  318.  * getpeername --
  319.  *
  320.  *    Find out the remote address that this socket is connected to.
  321.  *
  322.  * Results:
  323.  *    If 0        - Successful.
  324.  *    If UNIX_ERROR, then errno = 
  325.  *    EINVAL        - Bad size for *namePtr.
  326.  *    ENOTCONN    - The socket is not connected.
  327.  *    EFAULT        - Invalid argument to the ioctl.
  328.  *
  329.  * Side effects:
  330.  *    None.
  331.  *
  332.  *----------------------------------------------------------------------
  333.  */
  334.  
  335. int
  336. Fs_GetpeernameStub(socketID, namePtr, nameLenPtr)
  337.     int            socketID;    /* Stream ID of socket connected to 
  338.                      * remote peer. */
  339.     struct sockaddr    *namePtr;    /* Upon return, <addr,port> for 
  340.                      * remote peer. */
  341.     int            *nameLenPtr;    /* Size of *namePtr. (in/out) */
  342. {
  343.     ReturnStatus    status;
  344.     int            nameLen;
  345.  
  346.     if (debugFsStubs) {
  347.     printf("Fs_GetpeernameStub(%d, %x, %x)\n", socketID, namePtr,
  348.         nameLenPtr);
  349.     }
  350.     if (nameLenPtr == (int *) NULL) {
  351.     Mach_SetErrno(EINVAL);
  352.     return -1;
  353.     }
  354.     status = Vm_CopyIn(sizeof(int), (Address)nameLenPtr, (Address)&nameLen);
  355.     if (status != SUCCESS) {
  356.     Mach_SetErrno(Compat_MapCode(status));
  357.     return -1;
  358.     }
  359.     if (nameLen < sizeof(struct sockaddr_in)) {
  360.     Mach_SetErrno(EINVAL);
  361.     return -1;
  362.     }
  363.     if (nameLen > sizeof(struct sockaddr_in)) {
  364.     nameLen = sizeof(struct sockaddr_in);
  365.     status = Vm_CopyOut(sizeof(int),(Address)&nameLen, (Address)nameLenPtr);
  366.     if (status != SUCCESS) {
  367.         Mach_SetErrno(Compat_MapCode(status));
  368.         return -1;
  369.     }
  370.     }
  371.     status = Fs_IOControlStub(socketID, IOC_NET_GET_REMOTE_ADDR, 
  372.             0, (Address) NULL, 
  373.             nameLen, (Address) namePtr);
  374.     if (status != SUCCESS) {
  375.     DebugMsg(status, "getpeername");
  376.     Mach_SetErrno(Compat_MapCode(status));
  377.     return -1;
  378.     }
  379.     return 0;
  380. }
  381.  
  382.  
  383. /*
  384.  *----------------------------------------------------------------------
  385.  *
  386.  * getsockname --
  387.  *
  388.  *    Find out the local address for this socket, which was
  389.  *    set with the bind routine or by the connect routine.
  390.  *
  391.  * Results:
  392.  *    If 0        - Successful.
  393.  *    If UNIX_ERROR, then errno = 
  394.  *    EINVAL        - Bad size for *namePtr.
  395.  *    EFAULT        - Invalid argument to the ioctl.
  396.  *
  397.  * Side effects:
  398.  *    None.
  399.  *
  400.  *----------------------------------------------------------------------
  401.  */
  402.  
  403. int
  404. Fs_GetsocknameStub(socketID, namePtr, nameLenPtr)
  405.     int            socketID;    /* Stream ID of socket to get name of.*/
  406.     struct sockaddr    *namePtr;    /* Upon return, current <addr,port> for
  407.                      * this socket. */
  408.     int            *nameLenPtr;    /* Size of *namePtr. (in/out) */
  409. {
  410.     ReturnStatus    status;
  411.     int            nameLen;
  412.  
  413.     if (debugFsStubs) {
  414.     printf("Fs_GetsocknameStub(%d, %x, %x)\n", socketID, namePtr,
  415.         nameLenPtr);
  416.     }
  417.     if (nameLenPtr == (int *) NULL) {
  418.     Mach_SetErrno(EINVAL);
  419.     return -1;
  420.     }
  421.     status = Vm_CopyIn(sizeof(int), (Address)nameLenPtr, (Address)&nameLen);
  422.     if (status != SUCCESS) {
  423.     Mach_SetErrno(Compat_MapCode(status));
  424.     return -1;
  425.     }
  426.     if (nameLen < sizeof(struct sockaddr_in)) {
  427.     Mach_SetErrno(EINVAL);
  428.     return -1;
  429.     }
  430.     if (nameLen > sizeof(struct sockaddr_in)) {
  431.     nameLen = sizeof(struct sockaddr_in);
  432.     status = Vm_CopyOut(sizeof(int),(Address)&nameLen, (Address)nameLenPtr);
  433.     if (status != SUCCESS) {
  434.         Mach_SetErrno(Compat_MapCode(status));
  435.         return -1;
  436.     }
  437.     }
  438.  
  439.     status = Fs_IOControlStub(socketID, IOC_NET_GET_LOCAL_ADDR, 
  440.                   0, (Address) NULL, 
  441.                   nameLen, (Address) namePtr);
  442.  
  443.     if (status != SUCCESS) {
  444.     DebugMsg(status, "getsockname");
  445.     Mach_SetErrno(Compat_MapCode(status));
  446.     return -1;
  447.     }
  448.     return 0;
  449. }
  450.  
  451. /*
  452.  *----------------------------------------------------------------------
  453.  *
  454.  * getsockopt --
  455.  *
  456.  *    Get the value for a socket option.
  457.  *
  458.  * Results:
  459.  *    If 0        - Successful.
  460.  *    If UNIX_ERROR, then errno = 
  461.  *    EFAULT        - Invalid argument to the ioctl.
  462.  *
  463.  * Side effects:
  464.  *    None.
  465.  *
  466.  *----------------------------------------------------------------------
  467.  */
  468. int
  469. Fs_GetsockoptStub(socketID, level, optName, optVal, optLenPtr)
  470.     int        socketID;    /* Stream ID of socket to get options on. */
  471.     int        level;        /* Socket or protocol level to get the option.*/
  472.     int        optName;    /* Type of option to get. */
  473.     char    *optVal;    /* Address of buffer to store the result. */
  474.     int        *optLenPtr;    /* In: Size of *optVal, out: # of bytes stored
  475.                  * in *optVal. */
  476. {
  477.     ReturnStatus    status;
  478.     int            optionsArray[2];
  479.     int            optLen;
  480.     Address             tmp;
  481.  
  482.     if (debugFsStubs) {
  483.     printf("Fs_GetsockoptStub(%d, %d, %d, %x, %x)\n", socketID,
  484.         level, optName, optVal, optLenPtr);
  485.     }
  486.  
  487.     /*
  488.      * OptionsArray is used to give the server the values of "level"
  489.      * and "optName". A buffer ("newBufPtr") is needed to get the option
  490.      * value and the length of the value.
  491.      */
  492.     optionsArray[0] = level;
  493.     optionsArray[1] = optName;
  494.  
  495.     status = Vm_CopyIn(sizeof(int), (Address)optLenPtr, (Address)&optLen);
  496.     if (status != SUCCESS) {
  497.     return(status);
  498.     }
  499.     tmp = malloc(optLen);
  500.     status = IOControlStub(socketID, IOC_NET_GET_OPTION,
  501.             sizeof(optionsArray), (Address) optionsArray, 
  502.             optLen, tmp);
  503.  
  504.     if (status != SUCCESS) {
  505.     DebugMsg(status, "getsockopt");
  506.     Mach_SetErrno(Compat_MapCode(status));
  507.     return -1;
  508.     }
  509.     if (optName == SO_ERROR) {
  510.     /*
  511.      * The error value is a Sprite ReturnStatus so we must convert it
  512.      * to the equivalent Unix value.
  513.      */
  514.     * (int *) tmp = Compat_MapCode(* (int *) tmp);
  515.     }
  516.     status = Vm_CopyOut(optLen, tmp, optVal);
  517.     if (status != SUCCESS) {
  518.     Mach_SetErrno(Compat_MapCode(status));
  519.     return -1;
  520.     }
  521.     return 0;
  522. }
  523.  
  524. /*
  525.  *----------------------------------------------------------------------
  526.  *
  527.  * setsockopt --
  528.  *
  529.  *    Set the value for a socket option.
  530.  *
  531.  * Results:
  532.  *    If 0        - Successful.
  533.  *    If UNIX_ERROR, then errno = 
  534.  *    EFAULT        - Invalid argument to the ioctl.
  535.  *
  536.  * Side effects:
  537.  *    None.
  538.  *
  539.  *----------------------------------------------------------------------
  540.  */
  541.  
  542. /*VARARGS*/
  543. int
  544. Fs_SetsockoptStub(socketID, level, optName, optVal, optLen)
  545.     int        socketID;    /* Stream ID of socket to set options on. */
  546.     int        level;        /* Socket or protocol level to get the option.*/
  547.     int        optName;    /* Type of option to get. */
  548.     char    *optVal;    /* Address of buffer to store the result. */
  549.     int        optLen;        /* Size of *optVal. */
  550. {
  551.     ReturnStatus    status;
  552.     int            *kernBufPtr;
  553.  
  554.     if (debugFsStubs) {
  555.     printf("Fs_SetsockoptStub(%d, %d, %d, %x, %d)\n", socketID,
  556.         level, optName, optVal, optLen);
  557.     }
  558.     kernBufPtr = (int *)malloc(2 * sizeof(int) + optLen);
  559.     kernBufPtr[0] = level;
  560.     kernBufPtr[1] = optName;
  561.     status = Vm_CopyIn(optLen, (Address)optVal, (Address)&kernBufPtr[2]);
  562.     if (status != SUCCESS) {
  563.     free((Address)kernBufPtr);
  564.     Mach_SetErrno(Compat_MapCode(status));
  565.     return -1;
  566.     }
  567.     status = IOControlStub(socketID, IOC_NET_SET_OPTION,
  568.                   2 * sizeof(int) + optLen, (Address)kernBufPtr,
  569.                   0, (Address) NULL);
  570.     free((Address)kernBufPtr);
  571.     if (status != SUCCESS) {
  572.     DebugMsg(status, "getsockopt");
  573.     Mach_SetErrno(Compat_MapCode(status));
  574.     return -1;
  575.     }
  576.     return 0;
  577. }
  578.  
  579. /*
  580.  *----------------------------------------------------------------------
  581.  *
  582.  * listen --
  583.  *
  584.  *    Allows a stream socket to accept remote connection requests and to
  585.  *    specify how many such requests will be queued up before they 
  586.  *    are refused.
  587.  *
  588.  * Results:
  589.  *    If 0        - Successful.
  590.  *    If UNIX_ERROR, then errno = 
  591.  *    EOPNOTSUPP    - The socket type doesn't allow a listen operation.
  592.  *    EFAULT        - Invalid argument to the ioctl.
  593.  *
  594.  * Side effects:
  595.  *    None.
  596.  *
  597.  *----------------------------------------------------------------------
  598.  */
  599.  
  600. ReturnStatus
  601. Fs_ListenStub(socketID, backlog)
  602.     int    socketID;    /* Stream ID of socket to be put in listen mode. */
  603.     int    backlog;    /* How many connection requests to queue. */
  604. {
  605.     ReturnStatus    status;
  606.  
  607.     if (debugFsStubs) {
  608.     printf("Fs_ListenStub(%d, %d)\n", socketID, backlog);
  609.     }
  610.     status = IOControlStub(socketID, IOC_NET_LISTEN,
  611.             sizeof(backlog), (Address) &backlog,
  612.             0, (Address) NULL);
  613.     if (status != SUCCESS) {
  614.     DebugMsg(status, "listen");
  615.     Mach_SetErrno(Compat_MapCode(status));
  616.     return -1;
  617.     }
  618.     return 0;
  619. }
  620.  
  621. /*
  622.  *----------------------------------------------------------------------
  623.  *
  624.  * recv --
  625.  *
  626.  *    Read data from a connected socket. 
  627.  *
  628.  * Results:
  629.  *    See recvfrom().
  630.  *
  631.  * Side effects:
  632.  *    None.
  633.  *
  634.  *----------------------------------------------------------------------
  635.  */
  636.  
  637. int
  638. Fs_RecvStub(socketID, bufPtr, bufSize, flags)
  639.     int        socketID;
  640.     char    *bufPtr;    /* Address of buffer to place the data in. */
  641.     int        bufSize;    /* Size of *bufPtr. */
  642.     int        flags;        /* Type of operatrion: OR of MSG_OOB, MSG_PEEK*/
  643. {
  644.     if (debugFsStubs) {
  645.     printf("Fs_RecvStub(%d, %x, %d, %d)\n", socketID, bufPtr, bufSize,
  646.         flags);
  647.     }
  648.     return Fs_RecvfromStub(socketID, bufPtr, bufSize, flags, 
  649.                 (struct sockaddr *) NULL, (int *) NULL);
  650. }
  651.  
  652. /*
  653.  *----------------------------------------------------------------------
  654.  *
  655.  * recvfrom --
  656.  *
  657.  *    Read data from a socket.
  658.  *
  659.  * Results:
  660.  *    If 0        - Successful.
  661.  *    If UNIX_ERROR, then errno = 
  662.  *    EINVAL        - Bad size or address for senderPtr, senderLenPtr.
  663.  *    EWOULDBLOCK    - If non-blocking, no data are available.
  664.  *    EFAULT        - Invalid argument to the ioctl.
  665.  *
  666.  * Side effects:
  667.  *    None.
  668.  *
  669.  *----------------------------------------------------------------------
  670.  */
  671.  
  672. int
  673. Fs_RecvfromStub(socketID, bufPtr, bufSize, flags, senderPtr, 
  674.          senderLenPtr)
  675.     int            socketID;    /* Socket to read. */
  676.     char        *bufPtr;    /* Buffer to place the data in. */
  677.     int            bufSize;    /* Size of *bufPtr. */
  678.     int            flags;        /* Type of operatrion: OR of 
  679.                      *  MSG_OOB, MSG_PEEK*/
  680.     struct sockaddr    *senderPtr;    /* Address of sender of the data. */
  681.     int            *senderLenPtr;    /* Size of *senderPtr. (in/out) */
  682. {
  683.     ReturnStatus    status;
  684.     int            *intPtr;
  685.     int            senderLen;
  686.     int            value;
  687.  
  688.     if (debugFsStubs) {
  689.     printf("Fs_RecvfromStub(%d, %x, %d, %d, %x, %x)\n",
  690.         socketID, bufPtr, bufSize, flags, senderPtr, senderLenPtr);
  691.     }
  692.     intPtr = (int *)(Mach_UserStack() - sizeof(int));
  693.     if (senderPtr != (struct sockaddr *) NULL) {
  694.     if (senderLenPtr == (int *) NULL) {
  695.         return(SYS_INVALID_ARG);
  696.     }
  697.     status = Vm_CopyIn(sizeof(int), (Address)senderLenPtr,
  698.                (Address)&senderLen);
  699.     if (status != SUCCESS) {
  700.         return(status);
  701.     }
  702.     if (senderLen != sizeof(struct sockaddr_in)) {
  703.         Mach_SetErrno(EINVAL);
  704.         return -1;
  705.     }
  706.     }
  707.  
  708.     /*
  709.      * If there are flags, ship them to the server.
  710.      */
  711.     if (flags != 0) {
  712.     status = Vm_CopyOut(sizeof(flags), (Address)&flags, (Address)intPtr);
  713.     if (status != SUCCESS) {
  714.         return(status);
  715.     }
  716.     status = Fs_IOControlStub(socketID, IOC_NET_RECV_FLAGS,
  717.                   sizeof(flags), (Address)intPtr,
  718.                   0, (Address) NULL);
  719.     if (status != SUCCESS) {
  720.         DebugMsg(status, "recvfrom (ioctl recv_flags)");
  721.         Mach_SetErrno(Compat_MapCode(status));
  722.         return -1;
  723.     }
  724.     }
  725.  
  726.     status = Fs_ReadStub(socketID, bufSize, bufPtr, intPtr);
  727.     if (status != SUCCESS) {
  728.     DebugMsg(status, "recvfrom (read)");
  729.     Mach_SetErrno(Compat_MapCode(status));
  730.     return -1;
  731.     }
  732.     (void)Vm_CopyIn(sizeof(int), (Address)intPtr, (Address) &value);
  733.  
  734.     /*
  735.      * If the caller wants the address of the sender, ask the server for it.
  736.      */
  737.     if (senderPtr != (struct sockaddr *) NULL) {
  738.     status = Fs_IOControlStub(socketID, IOC_NET_RECV_FROM,
  739.                   0, (Address) NULL,
  740.                   senderLen, (Address) senderPtr);
  741.     if (status != SUCCESS) {
  742.         DebugMsg(status, "recvfrom (ioctl get_remote)");
  743.         Mach_SetErrno(Compat_MapCode(status));
  744.         return -1;
  745.     }
  746.     }
  747.     return value;
  748. }
  749.  
  750. /*
  751.  *----------------------------------------------------------------------
  752.  *
  753.  * recvmsg --
  754.  *
  755.  *    Read data from a socket using multiple buffers.
  756.  *
  757.  * Results:
  758.  *    If 0        - Successful.
  759.  *    If UNIX_ERROR, then errno = 
  760.  *    EINVAL        - Bad size or address for msg_name, msg_namelen;
  761.  *                I/O vector length too big.
  762.  *    EWOULDBLOCK    - If non-blocking, no data are available.
  763.  *    EFAULT        - Invalid argument to the ioctl, null address 
  764.  *               for msgPtr.
  765.  *
  766.  * Side effects:
  767.  *    None.
  768.  *
  769.  *----------------------------------------------------------------------
  770.  */
  771.  
  772. int
  773. Fs_RecvmsgStub(socketID, msgPtr, flags)
  774.     int            socketID;    /* Sokect to read data from. */
  775.     struct msghdr    *msgPtr;    /* I/O vector of buffers to store the
  776.                      * data. */
  777.     int            flags;        /* Type of operatrion: OR of 
  778.                      *  MSG_OOB, MSG_PEEK*/
  779. {
  780.     int            *intPtr;
  781.     ReturnStatus    status;
  782.     struct msghdr    msg;
  783.  
  784.     if (debugFsStubs) {
  785.     printf("Fs_RecvmsgStub(%d, %x, %d)\n", socketID, msgPtr, flags);
  786.     }
  787.     if (msgPtr == (struct msghdr *) NULL) {
  788.     Mach_SetErrno(EACCES);
  789.     return -1;
  790.     }
  791.     status = Vm_CopyIn(sizeof(msg), (Address)msgPtr, (Address)&msg);
  792.     if (status != SUCCESS) {
  793.     Mach_SetErrno(Compat_MapCode(status));
  794.     return -1;
  795.     }
  796.  
  797.     if (msg.msg_name != (Address) NULL) {
  798.     if (msg.msg_namelen != sizeof(struct sockaddr_in)) {
  799.         Mach_SetErrno(EINVAL);
  800.         return -1;
  801.     }
  802.     }
  803.  
  804.     if (msg.msg_iovlen > MSG_MAXIOVLEN) {
  805.         Mach_SetErrno(EINVAL);
  806.         return -1;
  807.     }
  808.  
  809.     intPtr = (int *)(Mach_UserStack() - sizeof(int));
  810.     /*
  811.      * If there are flags, ship them to the server.
  812.      */
  813.     if (flags != 0) {
  814.     status = Vm_CopyOut(sizeof(flags), (Address)&flags, (Address)intPtr);
  815.     if (status != SUCCESS) {
  816.         Mach_SetErrno(Compat_MapCode(status));
  817.         return -1;
  818.     }
  819.     status = Fs_IOControlStub(socketID, IOC_NET_RECV_FLAGS,
  820.                 sizeof(flags), (Address)intPtr,
  821.                 0, (Address) NULL);
  822.     if (status != SUCCESS) {
  823.         DebugMsg(status, "recvmsg (ioctl recv_flags)");
  824.         Mach_SetErrno(Compat_MapCode(status));
  825.         return -1;
  826.     }
  827.     }
  828.     status = Fs_ReadvStub(socketID, msg.msg_iov, msg.msg_iovlen);
  829.     if (status != SUCCESS) {
  830.     Mach_SetErrno(Compat_MapCode(status));
  831.     return -1;
  832.     }
  833.  
  834.     /*
  835.      * If the caller wants the address of the sender, ask the server for it.
  836.      */
  837.     if (msg.msg_name != (Address) NULL) {
  838.     status = Fs_IOControlStub(socketID, IOC_NET_RECV_FROM,
  839.             0, (Address) NULL,
  840.             msg.msg_namelen, (Address) msg.msg_name);
  841.     if (status != SUCCESS) {
  842.         DebugMsg(status, "recvmsg (ioctl recv_from)");
  843.         Mach_SetErrno(Compat_MapCode(status));
  844.         return -1;
  845.     }
  846.     }
  847.     return 0;
  848. }
  849.  
  850. /*
  851.  *----------------------------------------------------------------------
  852.  *
  853.  * send --
  854.  *
  855.  *    Write data to a connected socket.
  856.  *
  857.  * Results:
  858.  *    See sendto().
  859.  *
  860.  * Side effects:
  861.  *    None.
  862.  *
  863.  *----------------------------------------------------------------------
  864.  */
  865.  
  866. int
  867. Fs_SendStub(socketID, bufPtr, bufSize, flags)
  868.     int        socketID;    /* Socket to send data on. */
  869.     char    *bufPtr;    /* Address of buffer to send. */
  870.     int        bufSize;    /* Size of *bufPtr. */
  871.     int        flags;        /* Type of operatrion: OR of 
  872.                  *  MSG_OOB, MSG_PEEK, MSG_DONTROUTE. */
  873. {
  874.  
  875.     return Fs_SendtoStub(socketID, bufPtr, bufSize, flags,
  876.                      (struct sockaddr *)NULL, 0);
  877. }
  878.  
  879. /*
  880.  *----------------------------------------------------------------------
  881.  *
  882.  * sendto --
  883.  *
  884.  *    Send a message from a socket.
  885.  *
  886.  * Results:
  887.  *    If 0        - Successful.
  888.  *    If UNIX_ERROR, then errno = 
  889.  *    EINVAL        - Bad size or address for destPtr, destLen..
  890.  *    EWOULDBLOCK    - If non-blocking, the server buffers are too
  891.  *              full to accept the data.
  892.  *    EMSGSIZE    - The buffer is too large to be sent in 1 packet.
  893.  *    EFAULT        - Invalid argument to the ioctl.
  894.  *
  895.  * Side effects:
  896.  *    None.
  897.  *
  898.  *----------------------------------------------------------------------
  899.  */
  900.  
  901. int
  902. Fs_SendtoStub(socketID, bufPtr, bufSize, flags, destPtr, destLen)
  903.     int        socketID;    /* Socket to send data on. */
  904.     char    *bufPtr;    /* Address of buffer to send. */
  905.     int        bufSize;    /* Size of *bufPtr. */
  906.     int        flags;        /* Type of operatrion: OR of 
  907.                  *  MSG_OOB, MSG_PEEK, MSG_DONTROUTE. */
  908.     struct sockaddr    *destPtr;    /* Destination to send the data to. */
  909.     int            destLen;    /* Size of *destPtr.  */
  910. {
  911.     ReturnStatus    status;
  912.  
  913.     if (debugFsStubs) {
  914.     printf("Fs_SendtoStub(%d, %x, %d, %d)\n", socketID, bufPtr,
  915.         bufSize, flags);
  916.     }
  917.     /*
  918.      * If either the flags or a destination are given, send them to the server.
  919.      */
  920.     if ((flags != 0) || (destPtr != (struct sockaddr *) NULL)) {
  921.     Net_SendInfo    sendInfo;
  922.  
  923.     if (destPtr != (struct sockaddr *) NULL) {
  924.         if (destLen != sizeof(struct sockaddr_in)) {
  925.         Mach_SetErrno(EINVAL);
  926.         return -1;
  927.         }
  928.         sendInfo.addressValid = TRUE;
  929.         status = Vm_CopyIn(sizeof(Net_InetSocketAddr), (Address)destPtr,
  930.               (Address)&sendInfo.address.inet);
  931.         if (status != SUCCESS) {
  932.         Mach_SetErrno(EFAULT);
  933.         return -1;
  934.         }
  935.     } else {
  936.         sendInfo.addressValid = FALSE;
  937.     }
  938.     sendInfo.flags = flags;
  939.     status = IOControlStub(socketID, IOC_NET_SEND_INFO,
  940.             sizeof(sendInfo), (Address) &sendInfo,
  941.             0, (Address) NULL);
  942.     if (status != SUCCESS) {
  943.         DebugMsg(status, "sendto (ioctl)");
  944.         Mach_SetErrno(Compat_MapCode(status));
  945.         return -1;
  946.     }
  947.     }
  948.     return Fs_NewWriteStub(socketID, bufPtr, bufSize);
  949. }
  950.  
  951. /*
  952.  *----------------------------------------------------------------------
  953.  *
  954.  * sendmsg --
  955.  *
  956.  *    Send a message from a socket.
  957.  *
  958.  * Results:
  959.  *    If 0        - Successful.
  960.  *    If UNIX_ERROR, then errno = 
  961.  *    EINVAL        - Bad size or address for msg_name, msg_namelen;
  962.  *                I/O vector length too big.
  963.  *    EWOULDBLOCK    - If non-blocking, the server buffers are too full 
  964.  *              accept the data.
  965.  *    EFAULT        - Invalid argument to the ioctl, null address 
  966.  *               for msgPtr.
  967.  *
  968.  * Side effects:
  969.  *    None.
  970.  *
  971.  *----------------------------------------------------------------------
  972.  */
  973.  
  974. int
  975. Fs_SendmsgStub(socketID, msgPtr, flags)
  976.     int            socketID;    /* Socket to send data on. */
  977.     struct msghdr    *msgPtr;    /* I/O vector of buffers containing
  978.                      * data to send. */
  979.     int            flags;        /* Type of operatrion: OR of 
  980.                      *  MSG_OOB, MSG_PEEK, MSG_DONTROUTE. */
  981. {
  982.     ReturnStatus    status;
  983.     struct msghdr    msg;
  984.  
  985.     if (debugFsStubs) {
  986.     printf("Fs_SendmsgStub(%d, %x, %d)\n", socketID, msgPtr, flags);
  987.     }
  988.  
  989.     if (msgPtr == (struct msghdr *) NULL) {
  990.     Mach_SetErrno(EACCES);
  991.     return -1;
  992.     }
  993.     status = Vm_CopyIn(sizeof(msg), (Address)msgPtr, (Address)&msg);
  994.     if (status != SUCCESS) {
  995.     Mach_SetErrno(EFAULT);
  996.     return -1;
  997.     }
  998.     if (msg.msg_iovlen > MSG_MAXIOVLEN) {
  999.     Mach_SetErrno(EINVAL);
  1000.     return -1;
  1001.     }
  1002.  
  1003.     if ((flags != 0) || (msg.msg_name != (Address) NULL)) {
  1004.     Net_SendInfo    sendInfo;
  1005.  
  1006.     if (msg.msg_name != (Address) NULL) {
  1007.         if (msg.msg_namelen != sizeof(struct sockaddr_in)) {
  1008.         Mach_SetErrno(EINVAL);
  1009.         return -1;
  1010.         }
  1011.         sendInfo.addressValid = TRUE;
  1012.         status = Vm_CopyIn(sizeof(Net_InetSocketAddr),
  1013.                    (Address)msg.msg_name,
  1014.                        (Address)&sendInfo.address.inet);
  1015.         if (status != SUCCESS) {
  1016.         Mach_SetErrno(EFAULT);
  1017.         return -1;
  1018.         }
  1019.     } else {
  1020.         sendInfo.addressValid = FALSE;
  1021.     }
  1022.     sendInfo.flags = flags;
  1023.     status = IOControlStub(socketID, IOC_NET_SEND_INFO,
  1024.                 sizeof(sendInfo), (Address) &sendInfo,
  1025.                 0, (Address) NULL);
  1026.  
  1027.     if (status != SUCCESS) {
  1028.         DebugMsg(status, "sendmsg (ioctl)");
  1029.         Mach_SetErrno(Compat_MapCode(status));
  1030.         return -1;
  1031.     }
  1032.     }
  1033.  
  1034.     return Fs_WritevStub(socketID, msg.msg_iov, msg.msg_iovlen);
  1035. }
  1036.  
  1037. /*
  1038.  *----------------------------------------------------------------------
  1039.  *
  1040.  * shutdown --
  1041.  *
  1042.  *    Shut down part of a full-duplex connection.
  1043.  *
  1044.  * Results:
  1045.  *    0        - The action was successful.
  1046.  *
  1047.  * Side effects:
  1048.  *    None.
  1049.  *
  1050.  *----------------------------------------------------------------------
  1051.  */
  1052.  
  1053. ReturnStatus
  1054. Fs_ShutdownStub(socketID, action)
  1055.     int        socketID;    /* Socket to shut down. */
  1056.     int        action;        /* 0 -> disallow further recvs, 
  1057.                  * 1 -> disallow further sends,
  1058.                  * 2 -> combination of above. */
  1059. {
  1060.     ReturnStatus    status;
  1061.  
  1062.     if (debugFsStubs) {
  1063.     printf("Fs_ShutdownStub(%d, %d)\n", socketID, action);
  1064.     }
  1065.     status = IOControlStub(socketID, IOC_NET_SHUTDOWN, 
  1066.             sizeof(action), (Address) &action,
  1067.             0, (Address) NULL);
  1068.  
  1069.     if (status != SUCCESS) {
  1070.     DebugMsg(status, "shutdown");
  1071.     Mach_SetErrno(Compat_MapCode(status));
  1072.     return -1;
  1073.     }
  1074.     return 0;
  1075. }
  1076.  
  1077. static ReturnStatus
  1078. IOControlStub(streamID, command, inBufSize, inBuffer,
  1079.                outBufSize, outBuffer)
  1080.     int     streamID;    /* User's handle on the stream */
  1081.     int     command;    /* IOControl command */
  1082.     int     inBufSize;    /* Size of inBuffer */
  1083.     Address     inBuffer;    /* Command specific input parameters */
  1084.     int     outBufSize;    /* Size of outBuffer */
  1085.     Address     outBuffer;    /* Command specific output parameters */
  1086. {
  1087.     Proc_ControlBlock *procPtr;
  1088.     Fs_ProcessState *fsPtr;
  1089.     Fs_Stream      *streamPtr;
  1090.     register ReturnStatus status = SUCCESS;
  1091.     Fs_IOCParam ioctl;
  1092.     Fs_IOReply reply;
  1093.  
  1094.     if (debugFsStubs) {
  1095.     printf("IOControlStub(%d, %x)\n", streamID, command);
  1096.     }
  1097.  
  1098.     /*
  1099.      * Get a stream pointer.
  1100.      */
  1101.     procPtr = Proc_GetEffectiveProc();
  1102.     status = Fs_GetStreamPtr(procPtr, streamID, &streamPtr);
  1103.     if (status != SUCCESS) {
  1104.     return(status);
  1105.     }
  1106.  
  1107.     if (!Fsutil_HandleValid(streamPtr->ioHandlePtr)) {
  1108.     return(FS_STALE_HANDLE);
  1109.     }
  1110.  
  1111.     ioctl.command = command;
  1112.     ioctl.format = mach_Format;
  1113.     ioctl.procID = procPtr->processID;
  1114.     ioctl.familyID = procPtr->familyID;
  1115.     ioctl.uid = procPtr->effectiveUserID;
  1116.  
  1117.     /*
  1118.      * Fast path for non-generic I/O controls to pseudo-devices.
  1119.      * We don't copy in/out the user's parameter blocks because the
  1120.      * pseudo-device code does direct cross-address-space copy later.
  1121.      * We also skip the check against large parameter blocks so arbitrary
  1122.      * amounts of data can be fed to and from a pseudo-device.
  1123.      */
  1124.     if ((streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM) &&
  1125.     (command > IOC_GENERIC_LIMIT)) {
  1126.     ioctl.inBufSize = inBufSize;
  1127.     ioctl.inBuffer = inBuffer;
  1128.     ioctl.outBufSize = outBufSize;  
  1129.     ioctl.outBuffer = outBuffer;
  1130.     ioctl.flags = FS_USER_IN|FS_USER_OUT;
  1131.     return(Fs_IOControl(streamPtr, &ioctl, &reply));
  1132.     }
  1133.  
  1134.     if (inBufSize > IOC_MAX_BYTES || outBufSize > IOC_MAX_BYTES) {
  1135.     return(SYS_INVALID_ARG);
  1136.     }
  1137.     ioctl.flags = 0;    /* We'll copy buffer's into/out of the kernel */
  1138.  
  1139.  
  1140.     if ((outBufSize > 0) && (outBuffer != (Address)0) &&
  1141.                 (outBuffer != (Address)NIL)){
  1142.     ioctl.outBuffer = outBuffer;
  1143.     ioctl.outBufSize = outBufSize;
  1144.     } else {
  1145.     ioctl.outBuffer = (Address)NIL;
  1146.     ioctl.outBufSize = outBufSize = 0;
  1147.     }
  1148.     if ((inBufSize > 0) && (inBuffer != (Address)0) &&
  1149.                (inBuffer != (Address)NIL)) {
  1150.     ioctl.inBuffer  = inBuffer;
  1151.     ioctl.inBufSize = inBufSize;
  1152.     } else {
  1153.     ioctl.inBuffer = (Address)NIL;
  1154.     ioctl.inBufSize = 0;
  1155.     }
  1156.     status = Fs_IOControl(streamPtr, &ioctl, &reply);
  1157.     if (status == SUCCESS) {
  1158.     /*
  1159.      * Post process the set/get flags stuff because the close-on-exec
  1160.      * flag is not kept down at the stream level, but up along
  1161.      * with the streamID.
  1162.      */
  1163.     fsPtr = procPtr->fsPtr;
  1164.     switch(command) {
  1165.  
  1166.         case IOC_GET_FLAGS: {
  1167.         if (fsPtr->streamFlags[streamID] & FS_CLOSE_ON_EXEC) {
  1168.             *(int *)ioctl.outBuffer |= IOC_CLOSE_ON_EXEC;
  1169.         }
  1170.         break;
  1171.         }
  1172.  
  1173.         case IOC_SET_BITS:
  1174.         case IOC_SET_FLAGS: {
  1175.         int flags;
  1176.         flags = *(int *)ioctl.inBuffer;
  1177.  
  1178.         if (flags & IOC_CLOSE_ON_EXEC) {
  1179.             fsPtr->streamFlags[streamID] |= FS_CLOSE_ON_EXEC;
  1180.         } else if (command == IOC_SET_FLAGS) {
  1181.             fsPtr->streamFlags[streamID] &= ~FS_CLOSE_ON_EXEC;
  1182.         }
  1183.         break;
  1184.         }
  1185.  
  1186.         case IOC_CLEAR_BITS:{
  1187.         int flags;
  1188.         flags = *(int *)ioctl.inBuffer;
  1189.         if (flags & IOC_CLOSE_ON_EXEC) {
  1190.             fsPtr->streamFlags[streamID] &= ~FS_CLOSE_ON_EXEC;
  1191.         }
  1192.         break;
  1193.         }
  1194.     }
  1195.     }
  1196.     return(status);
  1197. }
  1198.  
  1199.  
  1200. /*
  1201.  *----------------------------------------------------------------------
  1202.  *
  1203.  * Fs_SocketStub --
  1204.  *
  1205.  *    The stub for the "socket" Unix system call.
  1206.  *
  1207.  * Results:
  1208.  *    Returns -1 on failure.
  1209.  *
  1210.  * Side effects:
  1211.  *    Side effects associated with the system call.
  1212.  *     
  1213.  *
  1214.  *----------------------------------------------------------------------
  1215.  */
  1216. int
  1217. Fs_SocketStub(domain, type, protocol)
  1218.     int domain;         /* Type of communications domain */
  1219.     int type;           /* Type of socket: SOCK_STREAM, SOCK_DGRAM, SOCK_RAW. */
  1220.     int protocol;       /* Specific protocol to use. */
  1221. {
  1222.     int                status = 0;
  1223.     int                 streamID;
  1224.     int            err;
  1225.     Fs_IOReply          reply;
  1226.  
  1227.     if (debugFsStubs) {
  1228.     printf("Fs_SocketStub(%d, %d, %d)\n",domain, type, protocol);
  1229.     }
  1230.     if (domain != PF_INET) {
  1231.     Mach_SetErrno(EINVAL);
  1232.     return -1;
  1233.     }
  1234.  
  1235.     if (!gotHostName) {
  1236.     if (*sysHostName == '\0') {
  1237.         printf("*** host name uninitialized\n");
  1238.     } else {
  1239.         gotHostName = TRUE;
  1240.     }
  1241.         sprintf(streamDevice, INET_STREAM_NAME_FORMAT, sysHostName);
  1242.         sprintf(dgramDevice, INET_DGRAM_NAME_FORMAT, sysHostName);
  1243.         sprintf(rawDevice, INET_RAW_NAME_FORMAT, sysHostName);
  1244.     }
  1245.  
  1246.     if (type == SOCK_STREAM) {
  1247.         streamID = Fs_NewOpenStubInt(streamDevice, FS_READ|FS_WRITE, 0666);
  1248.     } else if (type == SOCK_DGRAM) {
  1249.         streamID = Fs_NewOpenStubInt(dgramDevice, FS_READ|FS_WRITE, 0666);
  1250.     } else if (type == SOCK_RAW) {
  1251.         streamID = Fs_NewOpenStubInt(rawDevice, FS_READ|FS_WRITE, 0666);
  1252.     } else {
  1253.     Mach_SetErrno(EINVAL);
  1254.         return -1;
  1255.     }
  1256.     if (streamID<0) {
  1257.     printf("Fs_SocketStub: open failure\n");
  1258.     return streamID;
  1259.     }
  1260.  
  1261.     if (protocol != 0) {
  1262.         status = Fs_IoctlInt(streamID, IOC_NET_SET_PROTOCOL,
  1263.         sizeof(int), (Address)&protocol, 0, NULL, &reply, &err);
  1264.     }
  1265.  
  1266.     if (status < 0) {
  1267.     printf("Fs_SocketStub: ioctl failure\n");
  1268.     return -1;
  1269.     }
  1270.     return streamID;
  1271. }
  1272.  
  1273. /*
  1274.  *----------------------------------------------------------------------
  1275.  *
  1276.  * connect --
  1277.  *
  1278.  *    For a stream socket, create a connection to a remote host.
  1279.  *    For a datagram socket, only receive datagrams from this remote 
  1280.  *    address.
  1281.  *
  1282.  * Results:
  1283.  *    If 0        - Successful.
  1284.  *    If UNIX_ERROR, then errno = 
  1285.  *    EINVAL        - Bad size for *namePtr,
  1286.  *    EADDRINUSE    - The address is already in use.
  1287.  *    EADDRNOTAVAIL    - The address is not valid for this host.
  1288.  *    EISCONN        - The socket is already connected.
  1289.  *    ETIMEDOUT    - The connection request timed-out.
  1290.  *    ECONNREFUSED    - The remote host refused the connection.
  1291.  *    ENETUNREACH    - The network isn't reachable from this host.
  1292.  *    EWOULDBLOCK    - If non-blocking, the connection can't be completed
  1293.  *                immediately.
  1294.  *    EFAULT        - Invalid argument to the ioctl.
  1295.  *
  1296.  * Side effects:
  1297.  *    A local address for the socket is given if it did not have one 
  1298.  *    already.
  1299.  *
  1300.  *----------------------------------------------------------------------
  1301.  */
  1302.  
  1303. int
  1304. Fs_ConnectStub(socketID, namePtr, nameLen)
  1305.     int            socketID;    /* Stream ID of socket. */
  1306.     struct sockaddr    *namePtr;    /* Remote address,port to connect to.*/
  1307.     int            nameLen;    /* Size of *namePtr. */
  1308. {
  1309.     ReturnStatus    status;
  1310.  
  1311.     if (nameLen != sizeof(struct sockaddr_in)) {
  1312.     return(SYS_INVALID_ARG);
  1313.     }
  1314.  
  1315.     status = Fs_IOControlStub(socketID, IOC_NET_CONNECT,
  1316.                   nameLen, (Address) namePtr, 
  1317.                   0, (Address) NULL);
  1318.  
  1319.     if (status == FS_WOULD_BLOCK) {
  1320.     int flags = 0;
  1321.     Address    usp;
  1322.     int *intPtr;
  1323.     int optionsArray[2];
  1324.     int *userOptionsArray;
  1325.  
  1326.     usp = (Address)Mach_UserStack();
  1327.     intPtr = (int *)(usp - sizeof(int));
  1328.     userOptionsArray = 
  1329.             (int *)(Mach_UserStack() - 3 * sizeof(int));
  1330.  
  1331.     /*
  1332.      * The connection didn't immediately complete, so wait if
  1333.      * we're blocking or return EWOULDBLOCK if we're non-blocking.
  1334.      */
  1335.     status = Fs_IOControlStub(socketID, IOC_GET_FLAGS, 
  1336.             0, (Address) NULL,
  1337.             sizeof(flags), (Address) intPtr);
  1338.  
  1339.     if (status != SUCCESS) {
  1340.         DebugMsg(status, "connect (ioctl)");
  1341.         UNIXRETURN(status);
  1342.     }
  1343.     (void)Vm_CopyIn(sizeof(flags), (Address)intPtr, (Address)&flags);
  1344.  
  1345.     if (flags & IOC_NON_BLOCKING) {
  1346.         UNIXRETURN(FS_WOULD_BLOCK);
  1347.     } 
  1348.  
  1349.     status = Wait(socketID, FALSE, &time_OneMinute);
  1350.  
  1351.     if (status == FS_TIMEOUT) {
  1352.         DebugMsg(status, "connect (select)");
  1353.         UNIXRETURN(status);
  1354.     }
  1355.  
  1356.     /*
  1357.      * See if the connection successfully completed.
  1358.      */
  1359.     optionsArray[0] = SOL_SOCKET;
  1360.     optionsArray[1] = SO_ERROR;
  1361.     status = Vm_CopyOut(2 * sizeof(int), (Address)optionsArray, 
  1362.                 (Address)userOptionsArray);
  1363.     if (status != SUCCESS) {
  1364.         UNIXRETURN(status);
  1365.     }
  1366.     status = Fs_IOControlStub(socketID, IOC_NET_GET_OPTION,
  1367.             sizeof(optionsArray), (Address) userOptionsArray, 
  1368.             sizeof(int), (Address) intPtr);
  1369.     if (status != SUCCESS) {
  1370.         DebugMsg(status, "connect (getsockopt)");
  1371.         UNIXRETURN(status);
  1372.     }
  1373.     (void)Vm_CopyIn(sizeof(int), (Address)intPtr, (Address)&status);
  1374.     } else if (status != SUCCESS) {
  1375.     DebugMsg(status, "connect");
  1376.     }
  1377.     UNIXRETURN(status);
  1378. }
  1379.  
  1380. /*ARGSUSED*/
  1381. /*
  1382.  *----------------------------------------------------------------------
  1383.  *
  1384.  * Fs_SocketpairStub --
  1385.  *
  1386.  *      The stub for the "socketpair" Unix system call.
  1387.  *
  1388.  * Results:
  1389.  *      Returns -1 on failure.
  1390.  *
  1391.  * Side effects:
  1392.  *      Side effects associated with the system call.
  1393.  *     
  1394.  *
  1395.  *----------------------------------------------------------------------
  1396.  */
  1397. int
  1398. Fs_SocketpairStub(d, type, protocol, sv)
  1399.     int d, type, protocol;
  1400.     int sv[2];
  1401. {
  1402.     printf("socketpair is not implemented\n");
  1403.     Mach_SetErrno(EINVAL);
  1404.     return -1;
  1405. }
  1406.  
  1407. /*
  1408.  *----------------------------------------------------------------------
  1409.  *
  1410.  * Wait --
  1411.  *
  1412.  *    Wait for the Inet server to indicate that a socket is ready
  1413.  *    for some action.
  1414.  *
  1415.  * Results:
  1416.  *    SUCCESS, or FS_TIMEOUT if a timeout occurred.
  1417.  *
  1418.  * Side effects:
  1419.  *    None.
  1420.  *
  1421.  *----------------------------------------------------------------------
  1422.  */
  1423.  
  1424. static ReturnStatus
  1425. Wait(socketID, readSelect, timeOutPtr)
  1426.     int     socketID;    /* Socket to wait on. */
  1427.     Boolean    readSelect;    /* If TRUE, select for reading, else select for
  1428.                  *  writing. */
  1429.     Time    *timeOutPtr;    /* Timeout to use for select. */
  1430. {
  1431.     ReturnStatus    status;
  1432.     int            numReady;
  1433.     Address        usp;
  1434.     int            *numReadyPtr;
  1435.     int            *userMaskPtr;
  1436.     Time        *userTimeOutPtr;
  1437.  
  1438.     if (debugFsStubs) {
  1439.     printf("Wait(%d, %d, %x)\n", socketID, readSelect, timeOutPtr);
  1440.     }
  1441.     usp = Mach_UserStack();
  1442.     usp -= sizeof(int);
  1443.     numReadyPtr = (int *)usp;
  1444.  
  1445.     if (timeOutPtr == (Time *)NULL) {
  1446.     userTimeOutPtr = (Time *)NULL;
  1447.     } else {
  1448.     usp -= sizeof(Time);
  1449.     userTimeOutPtr = (Time *)usp;
  1450.     status = Vm_CopyOut(sizeof(Time), (Address)timeOutPtr, 
  1451.                 (Address)userTimeOutPtr);
  1452.     if (status != SUCCESS) {
  1453.         return(status);
  1454.     }
  1455.     }
  1456.     /*
  1457.      * Wait until the Inet server indicates the socket is ready.
  1458.      */
  1459.  
  1460.     if (socketID < 32) {
  1461.     int    mask;
  1462.  
  1463.     usp -= sizeof(int);
  1464.     userMaskPtr = (int *)usp;
  1465.     mask = 1 << socketID;
  1466.     status = Vm_CopyOut(sizeof(int), (Address)&mask, (Address)userMaskPtr);
  1467.     if (status != SUCCESS) {
  1468.         return(status);
  1469.     }
  1470.     if (readSelect) {
  1471.         status = Fs_SelectStub(socketID, userTimeOutPtr, userMaskPtr,
  1472.                 (int *) NULL, (int *) NULL, numReadyPtr);
  1473.     } else {
  1474.         status = Fs_SelectStub(socketID, userTimeOutPtr, (int *) NULL, 
  1475.                 userMaskPtr, (int *) NULL, numReadyPtr);
  1476.     }
  1477.     } else {
  1478.     int    *maskPtr;
  1479.     int    numBytes;
  1480.  
  1481.     Bit_Alloc(socketID, maskPtr);
  1482.     Bit_Set(socketID, maskPtr);
  1483.     numBytes = Bit_NumBytes(socketID);
  1484.     usp -= numBytes;
  1485.     userMaskPtr = (int *)usp;
  1486.     status = Vm_CopyOut(numBytes, (Address)maskPtr, (Address)userMaskPtr);
  1487.     if (status != SUCCESS) {
  1488.         return(status);
  1489.     }
  1490.  
  1491.     if (readSelect) {
  1492.         status = Fs_SelectStub(socketID, userTimeOutPtr, userMaskPtr, 
  1493.                 (int *) NULL, (int *) NULL, numReadyPtr);
  1494.     } else {
  1495.         status = Fs_SelectStub(socketID, userTimeOutPtr, (int *) NULL,
  1496.                 userMaskPtr, (int *) NULL, numReadyPtr);
  1497.     }
  1498.     free((char *) maskPtr);
  1499.     }
  1500.  
  1501.     if (status == FS_TIMEOUT) {
  1502.     return(status);
  1503.     } else if (status != SUCCESS) {
  1504.     printf("Wait (socket.c): Fs_Select failed.\n");
  1505.     }
  1506.  
  1507.     (void)Vm_CopyIn(sizeof(int), (Address)numReadyPtr, (Address)&numReady);
  1508.     if (numReady != 1) {
  1509.     printf("Wait (socket.c): Fs_Select returned %d ready\n",
  1510.                 numReady);
  1511.     }
  1512.  
  1513.     return(SUCCESS);
  1514. }
  1515.